// Fill out your copyright notice in the Description page of Project Settings.

#include "StSreverLink.h"
#include "StSocketClient.h"
#include "StSocketTool.h"
#include "OutputDeviceRedirector.h"


UStSreverLink::UStSreverLink() 
{
	socketlink = NULL;
	linkID = -1;
	hotBuffer = -1;
	linkTime = 0;
	startTime = 0;//任务开始的时间
	failNumber = 0; //失败的数量
	tackUserTime = 0;//上一个成功任务耗时  单位毫秒
	tackNumber= SuccessNumber = 0;
	stage = EStWorkStage::UnLink;

}
UStSreverLink::~UStSreverLink() 
{
	onSuccessTack.Clear();
	StopLink();
}

bool UStSreverLink::TrySreverLink(int id,int hot, int ipa, int ipb, int ipc, int ipd, FSTSocketKeyEvent back)
{
	isTackIng = false;
	startTime = FStHheartBeat::GetNowTime();
	logPath = UStSocketTool::GetBasePath() + "worklog/";
	if (hot >= 80 && hot < 65535 && ipa >= 0 && ipa <= 255 && ipb >= 0 && ipb <= 255 && ipc >= 0 && ipc <= 255 && ipd >= 0 && ipd <= 255)
	{
		if (ipa == 0 && ipb == 0 && ipc == 0 && ipd == 0)return false;
		if (!socketlink)
		{
			linkID = id;
			hotBuffer = hot;
			ipBuffer = FString::Printf(TEXT("%i.%i.%i.%i"), ipa, ipb, ipc, ipd);
			linkPoint = FString::Printf(TEXT("%i.%i.%i.%i:%i"), ipa, ipb, ipc, ipd, hot);
			StageName = "Work" + FString::FromInt(hot);
			socketlink = new StSocketClient(linkID);
			socketlink->InitLink(ipa, ipb, ipc, ipd, hot);
			RepeatLink();
			onSuccessTack = back;
			logPath = UStSocketTool::GetBasePath() + "worklog/" + StageName + "/";
			return true;
		}
	}
	return false;

}


bool UStSreverLink::RepeatLink() 
{
	isTackIng = false;
	if (socketlink) 
	{
		if (socketlink->InRun())return true;	
		socketlink->StartLink();
		socketlink->AddOneMessage("startUpWorker\r\n\r\n");
		linkTime = 0;
		startTime = 0;//任务开始的时间
		tackNumber++; 	
		stage = EStWorkStage::StarTryLink;
		return true;
	}
	return false;
}


int UStSreverLink::GetID() 
{
	if (socketlink) 
	{
		return socketlink->linkID;
	}
	return -1;
}

bool UStSreverLink::TrayAddOneTask(FString mes,float f)
{
	UpDataLink(f);
	if (!isTackIng)//是否正在执行任务
	{
		//没有在执行任务。
		if (stage == EStWorkStage::WaitforAtask&&socketlink->GetMessageNum() == 0)
		{
			isTackIng = true;
			startTime = FStHheartBeat::GetNowTime();
			tackNumber++;
			socketlink->AddOneMessage(mes + "\r\n\r\n");//每条消息必须以"\r\n\r\n"	结尾
			UStSocketTool::WriteTxtDataToDisk(logPath + "mes_" + FString::FromInt(tackNumber) + "_" + UStSocketTool::GetTimeString() + ".txt", mes);
			stage = EStWorkStage::SendTask;
			return true;
		}
	}

	return false;
}


TEnumAsByte<EStWorkStage> UStSreverLink::GetLinkStage()
{
	return stage;
}


FString UStSreverLink::GetStageName()
{
	return StageName;
}

bool UStSreverLink::IsEqual(const int& hot, const FString ip)
{
	return hot == hotBuffer&&ip.Equals(ipBuffer);
}


FString UStSreverLink::GetLinkData()
{
	FString data = "{\"id\":" + FString::FromInt(linkID);
	data.Append(",\"name\":\"" + StageName + "\"");
	int fialnum = tackNumber - SuccessNumber;
	data.Append(",\"state\":\"");
	switch (stage)
	{
	case UnLink:
		data.Append("UnLink");
		break;
	case LinkIng:
		data.Append("LinkIng");
		break;
	case WaitforAtask:
		data.Append("WaitforAtask");
		break;
	case SendTask:
		data.Append("SendTask");
		fialnum--;
		break;
	case InWork:
		data.Append("InWork");
		fialnum--;
		break;
	case WorkFail:
		data.Append("WorkFail");
		break;
	case TaskOK:
		data.Append("TaskOK");
		fialnum--;
		break;
	case StarTryLink:
		data.Append("StarTryLink");
		break;
	default:
		data.Append("Unknown state");
		break;
	}
	data.Append(FString::Printf(TEXT("\",\"info\":\"%i/%i/%i\""), SuccessNumber, fialnum, int(tackUserTime / 1000)));

	data.Append("}");
	return data;
}

void UStSreverLink::StopLink() 
{
	if (socketlink)
	{
		socketlink->CloseSocket();
		delete socketlink;
		socketlink = NULL;
	}
}


TEnumAsByte<EStWorkStage> UStSreverLink::UpDataLink(float time)
{
	linkTime += time;

	if (socketlink&&socketlink->InLinking())
	{
		tackUserTime = FStHheartBeat::GetNowTime() - startTime;
		FString messgeBuffer;
	
		if (socketlink->GetOneMessage(messgeBuffer))//判断消息中是否包含关键字
		{
			if (messgeBuffer.Contains(INVALIDEMESSAGE))
			{
				isTackIng = false;
				failNumber++;
				onSuccessTack.ExecuteIfBound(-1);//任务失败返回-1；
				stage = EStWorkStage::WorkFail;
			}

			if (messgeBuffer.Contains(BACKOVER))
			{
				isTackIng = false;
				SuccessNumber++;	
				onSuccessTack.ExecuteIfBound((int)tackUserTime);//发现完成任务后回调返回耗时情况
				stage = EStWorkStage::TaskOK;
			}

			if (messgeBuffer.Contains(STARTRENDER))
			{
				stage = EStWorkStage::InWork;
				isTackIng = true;
			}
	
			if (messgeBuffer.Contains(WAITFORATASK))
			{				
				stage = EStWorkStage::WaitforAtask;
				isTackIng = false;
			}
			
			if (messgeBuffer.Contains(STOPSERVER))
			{
				stage = EStWorkStage::UnLink;
			}

		}
		else 
		{

			if (stage == EStWorkStage::WorkFail|| stage == EStWorkStage::TaskOK)//转换状态为等待任务
			{
				stage = EStWorkStage::WaitforAtask;//等待任务
			}
		}

		if (EStWorkStage::UnLink== stage)
		{
			startTime = FStHheartBeat::GetNowTime();
			stage = EStWorkStage::LinkIng;
		}
	}
	else
	{
		stage = EStWorkStage::UnLink;
		if (!heartTime.InWait())//掉线1分子后开始尝试重新连接
		{
			heartTime.SetAddTime(60000);		
		}
		else
		{		
			if (heartTime.needTrigger())
			{
				RepeatLink();
			}
		}
	}

	return stage;
}

//bool UStSreverLink::SendData(FString ss)
//{
//	if (socketlink)
//	{
//		socketlink->AddOneMessage(ss);
//	}
//	return false;
//}
//
//
//bool UStSreverLink::GetRvesData(FString& ss) 
//{
//	if (socketlink)
//	{
//		return socketlink->GetOneMessage(ss);
//	}
//	return false;
//}